package cn.iocoder.yudao.module.shop.service.itemtimes;

import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.shop.dal.dataobject.item.ShopItemDO;
import cn.iocoder.yudao.module.shop.dal.mysql.item.ShopItemMapper;
import cn.iocoder.yudao.module.shop.service.item.ShopItemService;
import cn.iocoder.yudao.module.shop.service.itemtimesrecord.ShopItemTimesRecordService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import cn.iocoder.yudao.module.shop.controller.admin.itemtimes.vo.*;
import cn.iocoder.yudao.module.shop.dal.dataobject.itemtimes.ShopItemTimesDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import cn.iocoder.yudao.module.shop.convert.itemtimes.ShopItemTimesConvert;
import cn.iocoder.yudao.module.shop.dal.mysql.itemtimes.ShopItemTimesMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.shop.enums.ErrorCodeConstants.*;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;

/**
 * 店内项目次数 Service 实现类
 *
 * @author 曹建伟
 */
@Service
@Validated
public class ShopItemTimesServiceImpl implements ShopItemTimesService {

    @Resource
    private ShopItemTimesMapper itemTimesMapper;

    @Resource
    private ShopItemService shopItemService;

    @Resource
    private ShopItemTimesRecordService shopItemTimesRecordService;

    @Override
    public Long createItemTimes(ShopItemTimesCreateReqVO createReqVO) {
        // 插入
        ShopItemTimesDO itemTimes = ShopItemTimesConvert.INSTANCE.convert(createReqVO);
        itemTimesMapper.insert(itemTimes);
        // 返回
        return itemTimes.getId();
    }

    @Override
    public void updateItemTimes(ShopItemTimesUpdateReqVO updateReqVO) {
        // 校验存在
        validateItemTimesExists(updateReqVO.getId());
        // 更新
        ShopItemTimesDO updateObj = ShopItemTimesConvert.INSTANCE.convert(updateReqVO);
        itemTimesMapper.updateById(updateObj);
    }

    @Override
    public void deleteItemTimes(Long id) {
        // 校验存在
        validateItemTimesExists(id);
        // 删除
        itemTimesMapper.deleteById(id);
    }

    private void validateItemTimesExists(Long id) {
        if (itemTimesMapper.selectById(id) == null) {
            throw exception(ITEM_TIMES_NOT_EXISTS);
        }
    }

    @Override
    public ShopItemTimesDO getItemTimes(Long id) {
        return itemTimesMapper.selectById(id);
    }

    @Override
    public ShopItemTimesDO getItemTimes(Long memberId, Long itemId){
        return itemTimesMapper.selectOne(new LambdaQueryWrapperX<ShopItemTimesDO>()
                .eq(ShopItemTimesDO::getMemberId, memberId)
                .eq(ShopItemTimesDO::getOptItemId, itemId));
    }

    @Override
    public List<ShopItemTimesDO> getItemTimesList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return ListUtil.empty();
        }
        return itemTimesMapper.selectBatchIds(ids);
    }

    @Override
    public List<ShopItemTimesDO> getAll(Long memberId){
        return itemTimesMapper.selectList(new LambdaQueryWrapperX<ShopItemTimesDO>()
                .eq(ShopItemTimesDO::getMemberId, memberId)
                .gt(ShopItemTimesDO::getNum, 0));
    }

    @Override
    public PageResult<ShopItemTimesDO> getItemTimesPage(ShopItemTimesPageReqVO pageReqVO) {
        return itemTimesMapper.selectPage(pageReqVO);
    }

    @Override
    public List<ShopItemTimesDO> getItemTimesList(ShopItemTimesExportReqVO exportReqVO) {
        return itemTimesMapper.selectList(exportReqVO);
    }

    @Override
    public void addTimes(Long memberId, Long itemId, Integer times, String reason, Integer price, Long tenantId){
        ShopItemDO itemDO = shopItemService.getItem(itemId);
        if(itemDO == null){
            throw exception(ITEM_NOT_EXISTS);
        }

        ShopItemTimesDO shopItemTimesDO = itemTimesMapper.selectOne(new LambdaQueryWrapperX<ShopItemTimesDO>()
                .eq(ShopItemTimesDO::getMemberId, memberId)
                .eq(ShopItemTimesDO::getOptItemId, itemId));

        if(shopItemTimesDO == null){
            ShopItemTimesCreateReqVO reqVO = new ShopItemTimesCreateReqVO();
            reqVO.setOptItemId(itemId);
            reqVO.setMemberId(memberId);
            reqVO.setNum(times);
            reqVO.setTenantId(tenantId);


            createItemTimes(reqVO);
            shopItemTimesDO = itemTimesMapper.selectOne(new LambdaQueryWrapperX<ShopItemTimesDO>()
                    .eq(ShopItemTimesDO::getMemberId, memberId)
                    .eq(ShopItemTimesDO::getOptItemId, itemId));
        }else {
            shopItemTimesDO.setNum(shopItemTimesDO.getNum() + times);
            itemTimesMapper.updateById(shopItemTimesDO);
        }

        shopItemTimesRecordService.record(memberId, itemId, times, shopItemTimesDO.getNum(), price, reason, tenantId);
    }

    @Override
    public void rollbackTimes(Long memberId, Long itemId, Integer times, String reason, Long tenantId){
        ShopItemTimesDO shopItemTimesDO = itemTimesMapper.selectOne(new LambdaQueryWrapperX<ShopItemTimesDO>()
                .eq(ShopItemTimesDO::getMemberId, memberId)
                .eq(ShopItemTimesDO::getOptItemId, itemId));

        shopItemTimesDO.setNum(shopItemTimesDO.getNum() + times);

        itemTimesMapper.updateById(shopItemTimesDO);

        shopItemTimesRecordService.record(memberId, itemId, times, shopItemTimesDO.getNum(), 0, reason, tenantId);
    }

    @Override
    public void subTimes(Long memberId, Long itemId, Integer times, String reason, Long tenantId){
        ShopItemTimesDO shopItemTimesDO = itemTimesMapper.selectOne(new LambdaQueryWrapperX<ShopItemTimesDO>()
                .eq(ShopItemTimesDO::getMemberId, memberId)
                .eq(ShopItemTimesDO::getOptItemId, itemId));

        if(shopItemTimesDO == null){
            throw exception(ITEM_TIMES_NOT_ENOUGH);
        }

        if(shopItemTimesDO.getNum() < times){
            throw exception(ITEM_TIMES_NOT_ENOUGH);
        }

        shopItemTimesDO.setNum(shopItemTimesDO.getNum()-times);

        itemTimesMapper.updateById(shopItemTimesDO);

        shopItemTimesRecordService.record(memberId, itemId, -times, shopItemTimesDO.getNum(), 0, reason, tenantId);
    }

}
